package com.sys.midware.hive.pool;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sys.midware.hive.config.BHiveConfig;



public class ConnectionPool implements IConnectionPool {
	private static final Logger logger = LoggerFactory.getLogger(ConnectionPool.class);

	/**
	 * 连接池配置属性
	 */
	private BHiveConfig dbConfig;

	/**
	 * 连接池活动状态
	 */
	private boolean isActive = false;

	/**
	 * 记录创建的总的连接数
	 */
	private int contActive = 0;

	/**
	 * 空闲连接
	 */
	private List<Connection> freeConnections = new Vector<Connection>();

	/**
	 * 活动连接
	 */
	private List<Connection> activeConnections = new Vector<Connection>();


	public ConnectionPool(BHiveConfig config) {
		super();
		this.dbConfig = config;
		init();
		checkPool();
		logger.trace("config=" + config.toString());
	}

	public void init() {
		try {
			for (int i = 0; i < dbConfig.getPoolConfig().getInitialSize(); i++) {
				Connection conn = newConnection();
				logger.debug("初始化最小连接数");
				if (conn != null) {
					freeConnections.add(conn);
					contActive++;
				}
			}
			isActive = true;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	public synchronized Connection getCurrentConnecton() {
	    Connection conn = getFreeConnection();
		while (conn == null) {
			wait(250);
			conn = getFreeConnection();
		}
		return conn;
	}

	private Connection getFreeConnection()  {
	    Connection conn = getConnection();
		if (conn == null) {
			createConnections(1);
			conn = getConnection();
			if (conn == null) {
				return null;
			}
		}
		return conn;
	}
	
	public synchronized Connection getConnection() {
		logger.trace("invoked");
		Connection conn = null;
		try {
			logger.trace("判断是否超过最大连接数限制");
			int maxConn =this.dbConfig.getPoolConfig().getMaxActive();
			if (contActive <= maxConn) {
				logger.trace("contActive:"+contActive + " < maxConn: "+ maxConn + " freeConnections:"+freeConnections.size() + " activeConnections:"+activeConnections.size());
				if (freeConnections.size() > 0) {
					
					conn = freeConnections.get(0);
					freeConnections.remove(0);
					if (!isValid(conn)) {
						conn = newConnection();
					}
					activeConnections.add(conn);
				}

			} else {
				logger.info("已达到最大连接数限制:"+maxConn);
			}
			
		}  catch (ClassNotFoundException e) {
			logger.info(e.toString(),e);
		}
		return conn;
	}

	private void createConnections(long numConnections) {
		
		try {
			for (int i = 0; i < numConnections; i++) {
				if ( contActive > this.dbConfig.getPoolConfig().getMaxActive()) {
					break;
				}
				Connection newConnection = newConnection();
				freeConnections.add(newConnection);
				contActive++;
			}
		} catch (ClassNotFoundException e) {
			logger.error(e.toString(),e);
		}
		

	}
	
	/**
	 * 获得新连接
	 * @return
	 * @throws ClassNotFoundException
	 */
	private synchronized Connection newConnection() throws ClassNotFoundException {
	    Connection connection = null;
		if (dbConfig != null) {
	        try {
	            Class.forName(dbConfig.getDriverClassName());
	            connection = DriverManager.getConnection(dbConfig.getUrl(), dbConfig.getUsername(), dbConfig.getPassword()); 
	        } catch (Exception e) {
	            logger.error("",e);
	        }
		}
		
		return connection;
	}

	/**
	 * 释放连接
	 * @param conn
	 */
	public synchronized void releaseConnection(Connection conn) {
		//回放不检查
		freeConnections.add(conn);
		activeConnections.remove(conn);
	}

	/**
	 * 判断连接是否可用
	 * @param conn
	 * @return
	 */
	private boolean isValid(Connection conn) {
		boolean flag = false;  
		
		 try {  
//			 Pong pong = conn.ping();
//             if (!pong.getVersion().equalsIgnoreCase("unknown")) {  
		     flag = true;  
//             }  
         } catch (Exception e) {  
        	 logger.error(e.toString(),e);  
         } 
		return flag;
	}

	/**
	 * 销毁连接池
	 */
	public synchronized void destroy() {
		isActive = false;
		contActive = 0;
		freeConnections = new Vector<Connection>();
		activeConnections = new Vector<Connection>();
	}

	/**
	 * 连接池状态
	 * @return
	 */
	@Override
	public boolean isActive() {
		return isActive;
	}
	
	private void wait(int mSeconds) {
		try {
			Thread.sleep(mSeconds);
		} catch (InterruptedException e) {
			logger.error(e.toString(),e);
		}
	}

	/**
	 * 定时检查连接池情况
	 */
	@Override
	public void checkPool() {
		if (dbConfig.getPoolConfig().isCheckPool()) {
			new Timer().schedule(new TimerTask() {
				@Override
				public void run() {
					// 1.对线程里面的连接状态
					// 2.连接池最小 最大连接数
					// 3.其他状态进行检查，因为这里还需要写几个线程管理的类，暂时就不添加了
					logger.info("空线池连接数：" + freeConnections.size()+"   活动连接数：：" + activeConnections.size()+"  总的连接数：" + contActive);
				}
			}, dbConfig.getPoolConfig().getCheckDelayMilSecond(), dbConfig.getPoolConfig().getCheckPeriodMilSecond());
		}
	}
}
